/*     */ package com.zimbra.cs.account.accesscontrol;
/*     */ 
/*     */ import com.zimbra.common.localconfig.KnownKey;
/*     */ import com.zimbra.common.localconfig.LC;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.stats.Counter;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.LruMap;
/*     */ import com.zimbra.common.util.MapUtil;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.account.Entry;
/*     */ import com.zimbra.cs.account.NamedEntry;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ class PermCacheManager
/*     */ {
/*  61 */   private static final int ACL_CACHE_TARGET_MAXSIZE = LC.acl_cache_target_maxsize.intValue();
/*  62 */   private static final long ACL_CACHE_TARGET_MAXAGE = LC.acl_cache_target_maxage.intValue() * 60000L;
/*  63 */   private static final int ACL_CACHE_CREDENTIAL_MAXSIZE = LC.acl_cache_credential_maxsize.intValue();
/*     */   
/*  65 */   private static PermCacheManager theInstance = new PermCacheManager();
/*     */   
/*     */   private LruMap<String, PermCache> targetCache;
/*     */   
/*  69 */   private Counter hitRate = new Counter();
/*     */   
/*     */   private long invalidatedAt;
/*     */   
/*     */ 
/*     */   static PermCacheManager getInstance()
/*     */   {
/*  76 */     return theInstance;
/*     */   }
/*     */   
/*     */   private PermCacheManager() {
/*  80 */     this.targetCache = MapUtil.newLruMap(ACL_CACHE_TARGET_MAXSIZE);
/*  81 */     invalidateCache();
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   synchronized void invalidateCache()
/*     */   {
/*  92 */     this.invalidatedAt = System.currentTimeMillis();
/*  93 */     this.targetCache.clear();
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   void invalidateCache(Entry target)
/*     */   {
/* 114 */     boolean invalidateAll = true;
/*     */     try
/*     */     {
/* 117 */       invalidateAll = TargetType.canBeInheritedFrom(target);
/*     */     } catch (ServiceException e) {
/* 119 */       ZimbraLog.acl.debug("unable to determine if all permission cache should be invalidated, invalidating permission cache on all entries", e);
/*     */     }
/*     */     
/*     */ 
/* 123 */     if (invalidateAll) {
/* 124 */       invalidateCache();
/*     */     } else {
/* 126 */       PermCache permCache = getPermCache(target, false);
/*     */       
/* 128 */       if (permCache != null) {
/* 129 */         permCache.reset();
/*     */       }
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   private synchronized PermCache getPermCache(Entry target, boolean createIfNotExist)
/*     */   {
/* 138 */     String cacheKey = getCacheKey(target);
/* 139 */     PermCache permCache = (PermCache)this.targetCache.get(cacheKey);
/*     */     
/* 141 */     if ((permCache == null) && (createIfNotExist)) {
/* 142 */       permCache = new PermCache(null);
/* 143 */       this.targetCache.put(cacheKey, permCache);
/*     */     }
/*     */     
/* 146 */     if (permCache != null) {
/* 147 */       permCache.resetIfExpired(this.invalidatedAt);
/*     */     }
/* 149 */     return permCache;
/*     */   }
/*     */   
/*     */   private String getCacheKey(Entry target)
/*     */   {
/* 154 */     if ((target instanceof NamedEntry)) {
/* 155 */       return ((NamedEntry)target).getId();
/*     */     }
/* 157 */     return target.getLabel();
/*     */   }
/*     */   
/*     */   private void updateHitRate(boolean hit) {
/* 161 */     this.hitRate.increment(hit ? 100L : 0L);
/*     */   }
/*     */   
/*     */   double getHitRate() {
/* 165 */     return this.hitRate.getAverage();
/*     */   }
/*     */   
/*     */   PermissionCache.CachedPermission get(Entry target, String key, Right right) {
/* 169 */     PermCache permCache = getPermCache(target, false);
/* 170 */     if (permCache == null) {
/* 171 */       updateHitRate(false);
/* 172 */       return PermissionCache.CachedPermission.NOT_CACHED;
/*     */     }
/*     */     
/* 175 */     PermissionCache.CachedPermission perm = permCache.get(key, right);
/* 176 */     updateHitRate(PermissionCache.CachedPermission.NOT_CACHED != perm);
/* 177 */     return perm;
/*     */   }
/*     */   
/*     */   void put(Entry target, String key, Right right, PermissionCache.CachedPermission perm) {
/* 181 */     PermCache permCache = getPermCache(target, true);
/* 182 */     permCache.put(key, right, perm);
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */   private static class PermCache
/*     */   {
/*     */     private long resetAt;
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */     private LruMap<String, byte[]> credentialToPermissionMap;
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */     private PermCache()
/*     */     {
/* 206 */       this.credentialToPermissionMap = MapUtil.newLruMap(PermCacheManager.ACL_CACHE_CREDENTIAL_MAXSIZE);
/* 207 */       reset();
/*     */     }
/*     */     
/*     */     private synchronized boolean isExpired(long timestamp) {
/* 211 */       return (this.resetAt <= timestamp) || (this.resetAt + PermCacheManager.ACL_CACHE_TARGET_MAXAGE < System.currentTimeMillis());
/*     */     }
/*     */     
/*     */ 
/*     */ 
/*     */ 
/*     */     private synchronized void reset()
/*     */     {
/* 219 */       this.resetAt = (System.currentTimeMillis() + 1L);
/* 220 */       this.credentialToPermissionMap.clear();
/*     */     }
/*     */     
/*     */     private synchronized void resetIfExpired(long timestamp) {
/* 224 */       if (isExpired(timestamp)) {
/* 225 */         reset();
/*     */       }
/*     */     }
/*     */     
/*     */     private synchronized PermissionCache.CachedPermission get(String credential, Right right) {
/* 230 */       byte[] cachedPerms = (byte[])this.credentialToPermissionMap.get(credential);
/* 231 */       if (cachedPerms == null)
/* 232 */         return PermissionCache.CachedPermission.NOT_CACHED;
/* 233 */       return PermCacheManager.CachedPerms.get(cachedPerms, right);
/*     */     }
/*     */     
/*     */     private synchronized void put(String credential, Right right, PermissionCache.CachedPermission perm) {
/* 237 */       byte[] cachedPerms = (byte[])this.credentialToPermissionMap.get(credential);
/* 238 */       if (cachedPerms == null) {
/* 239 */         cachedPerms = new byte[PermCacheManager.CachedPerms.getMaxPermArraySize()];
/* 240 */         this.credentialToPermissionMap.put(credential, cachedPerms);
/*     */       }
/* 242 */       PermCacheManager.CachedPerms.put(cachedPerms, right, perm);
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */   static class CachedPerms
/*     */   {
/*     */     private static final int RIGHTS_PER_BYTE = 2;
/*     */     
/*     */     static final short MASK_NO_MATCHING_ACL = 0;
/*     */     static final short MASK_ALLOWED = 1;
/*     */     static final short MASK_DENIED = 2;
/* 254 */     private static final byte[][] MASKS_PERMS = { { 16, 32, 64 }, { 1, 2, 4 } };
/*     */     
/*     */ 
/*     */ 
/*     */ 
/* 259 */     private static final byte[] MASKS_CLEAR = { 15, 112 };
/*     */     
/*     */ 
/*     */ 
/*     */     static int getMaxPermArraySize()
/*     */     {
/* 265 */       return Right.getMaxCacheIndex() / 2 + 1;
/*     */     }
/*     */     
/*     */     static PermissionCache.CachedPermission get(byte[] cachedPerms, Right right) {
/* 269 */       int rightIdx = right.getCacheIndex();
/* 270 */       int idx = rightIdx / 2;
/* 271 */       byte byteForRight = cachedPerms[idx];
/* 272 */       int mask = rightIdx % 2;
/*     */       
/* 274 */       if ((MASKS_PERMS[mask][0] & byteForRight) != 0)
/* 275 */         return PermissionCache.CachedPermission.NO_MATCHING_ACL;
/* 276 */       if ((MASKS_PERMS[mask][1] & byteForRight) != 0)
/* 277 */         return PermissionCache.CachedPermission.ALLOWED;
/* 278 */       if ((MASKS_PERMS[mask][2] & byteForRight) != 0) {
/* 279 */         return PermissionCache.CachedPermission.DENIED;
/*     */       }
/* 281 */       return PermissionCache.CachedPermission.NOT_CACHED;
/*     */     }
/*     */     
/*     */     static void put(byte[] cachedPerms, Right right, PermissionCache.CachedPermission perm) {
/* 285 */       int rightIdx = right.getCacheIndex();
/* 286 */       int idx = rightIdx / 2;
/* 287 */       byte byteForRight = cachedPerms[idx];
/* 288 */       int mask = rightIdx % 2;
/*     */       
/* 290 */       byteForRight = (byte)(byteForRight & MASKS_CLEAR[mask]);
/* 291 */       byteForRight = (byte)(byteForRight | MASKS_PERMS[mask][perm.getCacheMask()]);
/* 292 */       cachedPerms[idx] = byteForRight;
/*     */     }
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/account/accesscontrol/PermCacheManager.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */